﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// NotReviewedButNeeded
#pragma once

#include "GcmpDatabase.h"
#include "NdbObject.h"
#include "OwnerPtr.h"
#include "ElementId.h"
#include <set>
#include <map>
#include <vector>
#include <string>

namespace gcmp
{
    class ClassId;
    class ElementId;
    class IIOStream;
    class IDbObjectArchive;
    class RawMemory;

    /// \brief Ndb的Cloneable对象基类
    class GCMP_DATABASE_EXPORT NdbObjectCloneable : public NdbObject
    {
        DEFINE_CAST_DERIVED(gcmp::NdbObjectCloneable, gcmp::NdbObject)
    public:
        NdbObjectCloneable(void);
        virtual ~NdbObjectCloneable(void) = 0;

        /// \brief     获取类Id
        static const ClassId & GetClassId();

        /// \brief     返回对象中的所有的ElementId
        /// \param[in] pElementIds   找到的ElementId放入此set
        void ReportElementIds(
            std::set<ElementId>* pElementIds,
            std::unordered_map<ElementId, std::vector<std::wstring>, ElementIdHash>* pPaths = nullptr,
            std::vector<std::wstring>* pCurrentPath = nullptr
        ) const;

    public:
        /// \brief     克隆方法接口
        virtual OwnerPtr<NdbObjectCloneable> NdbClone() const = 0;

        /// \brief     重置方法接口
        virtual void NdbAssignByMove(OwnerPtr<NdbObjectCloneable> opSourceObject) = 0;

        /// \brief     将对象序列化到给定的archive中的接口
        /// \param[in] archive     给定的archive
        /// \return    返回以字节数计的序列化占用大小；-1表示失败
        virtual UInt64 NdbSerialize(IDbObjectArchive & archive) const = 0;

        /// \brief     从archive中反序列化到分配好的内存中的接口
        /// \param[in] pRawMemory  分配好的内存
        /// \param[in] archive     给定的archive
        /// \param[in] majorVersion     文件主版本
        /// \return    返回以字节数计的反序列化后占用的内存大小；-1表示失败
        virtual Int32 NdbUnserializeObjectToMemory(RawMemory *pRawMemory, IIOStream & ioStream, UInt32 majorVersion) = 0;

        /// \brief     从给定的内存中提取对象的接口
        /// \param[in] 给定的内存
        /// \param[in] majorVersion     文件主版本
        virtual void NdbExtractObjectFromMemory(const RawMemory& opRawMemory, UInt32 majorVersion) = 0;

        /// \brief     对象是否有属性含有ElementId
        virtual bool HasElementIdProperty() const { return false; }

        /// \brief     用给定的ElementId替换原有的属性中的ElementId
        /// \param[in] oldToNewMap 旧ElementId到新ElementId的映射
        virtual void ReplaceElementIds(const std::unordered_map<ElementId, ElementId, ElementIdHash>& oldToNewMap) {}

        /// \brief     输出ndb数据信息，内部使用
        virtual void NdbDump(IDbObjectArchive &archive) const {}

        /// \brief     属性修改后，发出通知。对NdbObjectCloneable对象来说没有实际动作。
        virtual void NotifyElementPostChange() {}

    private:
        virtual void ReportElementIdsImpl(
            std::set<ElementId>* pElementIds, 
            std::unordered_map<ElementId, std::vector<std::wstring>, ElementIdHash>* pPaths,
            std::vector<std::wstring>* pCurrentPath
        ) const;
    
    };

}


